﻿using Bystd.Geo.Geometries;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bystd.Geo.GeoParsers.GeoJson
{
    public class Feature<proT, geoT>
    {
        public string type { get; set; } = "Feature";
        public geoT geometry { get; set; }
        public proT properties { get; set; }
    }

    public class GeometryCollection<geoT>
    {
        public string type { get; set; } = "GeometryCollection";

        public geoT[] geometries { get; set; }
    }

    public class FeatureCollection<proT, geoT>
    {
        public string name { get; set; }
        public string type { get; set; } = "FeatureCollection";
        public JsonCrs crs { get; set; }
        public Feature<proT, geoT>[] features { get; set; }
    }

    public class JsonGeometry
    {
        public JsonGeometry()
        { }

        public JsonGeometry(GeoType type)
        {
            this.type = type;
        }
        public GeoType type { get; set; }
    }

    public class JsonCrs
    {
        public string type { get; set; }

        public JsonCrsProperties properties { get; set; }
    }

    public class JsonCrsProperties
    {
        public string name { get; set; }
    }

    public class JsonPoint : JsonGeometry
    {
        public JsonPoint() : base(GeoType.POINT)
        { }

        public double[] coordinates { get; set; }
    }

    public class JsonMultiPoint : JsonGeometry
    {
        public JsonMultiPoint() : base(GeoType.MULTIPOINT)
        { }

        public List<double[]> coordinates { get; set; }

        public void Add(double[] xy)
        {
            if (coordinates == null)
                coordinates = new List<double[]>(1);

            coordinates.Add(xy);
        }
    }

    public class JsonLineString : JsonGeometry
    {
        public JsonLineString() : base(GeoType.LINESTRING)
        { }

        public List<double[]> coordinates { get; set; }

        public void Add(double[] xy)
        {
            if (coordinates == null)
                coordinates = new List<double[]>(1);

            coordinates.Add(xy);
        }
    }

    public class JsonMultiLineString : JsonGeometry
    {
        public JsonMultiLineString() : base(GeoType.MULTILINESTRING)
        { }

        public List<List<double[]>> coordinates { get; set; }

        public void Add(JsonLineString lineString)
        {
            if (coordinates == null)
                coordinates = new List<List<double[]>>();

            coordinates.Add(lineString.coordinates);
        }
    }

    public class JsonPolygon : JsonGeometry
    {
        public JsonPolygon() : base(GeoType.POLYGON)
        { }

        public List<List<double[]>> coordinates { get; set; }

        public void Add(JsonLineString lineString)
        {
            if (coordinates == null)
                coordinates = new List<List<double[]>>(1);

            coordinates.Add(lineString.coordinates);
        }

        public void Add(double[] xy)
        {
            if (coordinates == null)
                coordinates = new List<List<double[]>>(1);

            if (coordinates[0].Count == 0)
                coordinates[0] = new List<double[]>(1);

            coordinates[0].Add(xy);
        }
    }

    public class JsonMultiPolygon : JsonGeometry
    {
        public JsonMultiPolygon() : base(GeoType.MULTIPOLYGON)
        {
            coordinates = new List<List<List<double[]>>>();
        }

        public List<List<List<double[]>>> coordinates { get; set; }

        public void Add(JsonPolygon polygon)
        {
            if (coordinates == null)
                coordinates = new List<List<List<double[]>>>(1);

            coordinates.Add(polygon.coordinates);
        }

        public void Add(double[] xy)
        {
            if (coordinates == null)
                coordinates = new List<List<List<double[]>>>(1);

            if (coordinates[0].Count == 0)
                coordinates.Add(new List<List<double[]>>(1));

            if (coordinates[0][0].Count == 0)
                coordinates[0][0] = new List<double[]>();

            coordinates[0][0].Add(xy);
        }
    }
}
